﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MMessaging.Address.Services;
using MMessaging.Address;
using MMessaging.MessagingEx.Common;
using MMessaging.RequestResponse.Test.Common;

namespace MMessaging.RequestResponse.Test.Services
{
	public class RestaurantService : 
		MAddressServiceBase, 
		ICookMessagesFunctions, 
		IWaitressMessagesFunctions
	{
		private CookMessagesPlugIn _cookPlugIn;
		private WaitressMessagesPlugIn _waitressPlugIn;

		public RestaurantService() : base(
			new MAddress("RestaurantAddress"),
			2000, // time-intervall for alife-message
			// roles of this service
			RestaurantGlobals.WaitressRole,
			RestaurantGlobals.CookRole)
		{
			_cookPlugIn = new CookMessagesPlugIn(ServiceAddress, this);
			_cookPlugIn.InitPlugIn(this, PostMessage);

			_waitressPlugIn = new WaitressMessagesPlugIn(ServiceAddress, this);
			_waitressPlugIn.InitPlugIn(this,PostMessage);
		}

		protected override void OnMessage(IMTask<Address.MAddressMessageBase> context)
		{
			// see handler
		}

		void ICookMessagesFunctions.OnKitchenOrder(IMTask<MAddressMessageBase> task, KitchenOrder msg)
		{
			task.SleepWithException(2000);
			_cookPlugIn.Send_KitchenOrderResponse(msg);
		}

		void IWaitressMessagesFunctions.OnOrder(IMTask<MAddressMessageBase> task, Order msg)
		{
			// order meal in kitchen *******************
			var resp = _cookPlugIn.KitchenOrder(task, RestaurantGlobals.CookRole, msg.OrderParts, 10000);
			if ( IsCanceling )
				return;
			_waitressPlugIn.Send_OrderResponse(msg, new List<string>());

			// waiting for guest asking for the bill ************
			task.WaitOnMessage("wait on asking for bill", currentMsg =>
			{
				return
 					currentMsg is AskForBill &&
					currentMsg.Sender == msg.Sender;
					
			});

			if (IsCanceling)
				return;

			var askForBillMsg = task.CurrentMessage as AskForBill;
			// calculate amount
			int amount = 0;
			foreach(var orderPart in msg.OrderParts)
				amount += RestaurantGlobals.Menu[orderPart];

			// send bill to guest
			_waitressPlugIn.Send_AskForBillResponse(askForBillMsg, amount);

			// waiting for payment ********************
			task.WaitOnMessage("waiting on paying", currentMsg =>
			{
				return
					currentMsg is Pay &&
					currentMsg.Sender == msg.Sender;
			});

			if (IsCanceling)
				return;

			// say ok and thanks
			var payMsg = task.CurrentMessage as Pay;
			_waitressPlugIn.Send_PayResponse(payMsg);

		}

		void IWaitressMessagesFunctions.OnAskForBill(IMTask<MAddressMessageBase> task, AskForBill msg)
		{
			// do this in the context of an order - see OnOrder()
		}

		void IWaitressMessagesFunctions.OnPay(IMTask<MAddressMessageBase> task, Pay msg)
		{
			// do this in the context of an order - see OnOrder()
		}

		void IWaitressMessagesFunctions.OnSayHelloToWaitress(IMTask<MAddressMessageBase> task, SayHelloToWaitress msg)
		{
			_waitressPlugIn.Send_SayHelloToWaitressResponse(msg);
		}
	}
}
